package com.fingard.dsp.bank.directbank.alipay01;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IAppOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqUnifiedOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsUnifiedOrder;
import com.fingard.text.StringHelper;
import com.fingard.text.XmlHelper;
import com.fingard.util.DateHelper;
import net.sf.json.JSONObject;

import java.util.*;

public class ALIPAY01AppOrder extends ALIPAY01Base implements IAppOrder {
    @Override
    public RetAtsUnifiedOrder submitAppOrder(ReqUnifiedOrder p_req) {
        if ("APP02".equals(p_req.reqHeader.commandCode)) {
            return submitAppOrder2(p_req);
        } else {
            return submitAppOrder1(p_req);
        }
    }

    public RetAtsUnifiedOrder submitAppOrder1(ReqUnifiedOrder p_req) {
        RetAtsUnifiedOrder retAts = new RetAtsUnifiedOrder();
        retAts.rdSeq = p_req.rdSeq;

        try {
            logIsExist();

            ActSetItem actItem = this.getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                alipayJsonRequest.put("body", p_req.attach);
                alipayJsonRequest.put("subject", XmlHelper.encode(p_req.description));
                String enable_pay_channels = getBankConfig().getValueAsString("enablePayChannels");
                if (!StringHelper.isNullOrEmpty(enable_pay_channels)) {
                    alipayJsonRequest.put("enable_pay_channels", enable_pay_channels);
                }
                alipayJsonRequest.put("out_trade_no", p_req.rdSeq);
                alipayJsonRequest.put("timeout_express", getValidTime(p_req.getValidTime()));
                alipayJsonRequest.put("total_amount", p_req.amount);
                if (StringHelper.hasAnyChar(actItem.sellerId)) {
                    alipayJsonRequest.put("seller_id", actItem.sellerId);
                }
                alipayJsonRequest.put("product_code", "QUICK_MSECURITY_PAY");

                // 实名信息
                JSONObject userInfoJson = new JSONObject();
                userInfoJson.put("name", p_req.oppActName);
                userInfoJson.put("mobile", p_req.cellPhone);
                userInfoJson.put("cert_type", convertCertTypeToBank(p_req.certType));
                userInfoJson.put("cert_no", p_req.certNumber);

                String authFlag = "F";
                if ("1".equals(p_req.realNameFlag)) {
                    authFlag = "T";
                } else if ("0".equals(p_req.realNameFlag)) {
                    authFlag = "F";
                } else {
                    if (StringHelper.hasAnyChar(p_req.oppActName) || StringHelper.hasAnyChar(p_req.certNumber) || StringHelper.hasAnyChar(p_req.cellPhone)) {
                        authFlag = "T";
                    }
                }

                userInfoJson.put("need_check_info", authFlag);

                if ("T".equals(authFlag)) {
                    alipayJsonRequest.put("ext_user_info", userInfoJson);
                }

                if (StringHelper.hasAnyChar(p_req.insureAreaCode) || StringHelper.hasAnyChar(p_req.sHTradeNo)) {
                    StringBuilder insuranceMsg = new StringBuilder();
                    insuranceMsg.append("\"{\\\"insuranceFlag\":\"T\"," +
                            "\"insureAreaCode\":\"" + p_req.insureAreaCode + "\"," +
                            "\"insuranceType\":\"alipay_auto_ins\",\"shTradeNo\":\"" + p_req.sHTradeNo + "\"}\"");
                    JSONObject insuranceInfo = new JSONObject();
                    insuranceInfo.put("insurance_info", insuranceMsg.toString());
                    alipayJsonRequest.put("extend_params", insuranceInfo);
                }

                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);

                if (StringHelper.hasAnyChar(signature)) {
                    retAts.respCode = "0";
                    retAts.respInfo = "成功";

                    retAts.customHashMap = new HashMap<String, String>();
                    retAts.customHashMap.put("AppId", actItem.appId);
                    retAts.customHashMap.put("Method", "alipay.trade.app.pay");
                    retAts.customHashMap.put("Format", "JSON");
                    retAts.customHashMap.put("Charset", getCharset());
                    retAts.customHashMap.put("SignType", signType);
                    retAts.customHashMap.put("Sign", signature);
                    retAts.customHashMap.put("TimeStamp", timestamp);
                    retAts.customHashMap.put("Version", "1.0");
                    retAts.customHashMap.put("NotifyUrl", actItem.notifyURL);
                    retAts.customHashMap.put("BizContent", bizContent);
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "本机签名失败,请检查密钥是否正确";
                    WriteBankLogStep3("本机签名失败,请检查密钥是否正确");
                }
            } else {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }

    /**
     * 参考文档：https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay
     * <p>
     * alipay.trade.app.pay(app支付接口2.0)
     * 外部商户APP唤起快捷SDK创建订单并支付
     * <p>
     *
     * @param p_req
     * @return
     */
    public RetAtsUnifiedOrder submitAppOrder2(ReqUnifiedOrder p_req) {
        RetAtsUnifiedOrder retAts = new RetAtsUnifiedOrder();
        retAts.rdSeq = p_req.rdSeq;

        try {
            logIsExist();

            ActSetItem actItem = this.getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                JSONObject alipayJsonRequest = new JSONObject();

                alipayJsonRequest.put("timeout_express", getValidTime(p_req.getValidTime()));
                alipayJsonRequest.put("total_amount", p_req.amount);
                alipayJsonRequest.put("product_code", "QUICK_MSECURITY_PAY");
                alipayJsonRequest.put("body", p_req.attach);
                alipayJsonRequest.put("subject", XmlHelper.encode(p_req.description));
                alipayJsonRequest.put("out_trade_no", p_req.rdSeq);
                alipayJsonRequest.put("time_expire", "");
                alipayJsonRequest.put("goods_type", "0");
                alipayJsonRequest.put("promo_params", "");
                alipayJsonRequest.put("passback_params", "");

                JSONObject extend_params = new JSONObject();
                extend_params.put("sys_service_provider_id", "");
                extend_params.put("hb_fq_num", "");
                extend_params.put("hb_fq_seller_percent", "");
                extend_params.put("industry_reflux_info", "");
                extend_params.put("card_type", "");
                alipayJsonRequest.put("extend_params", extend_params);
                alipayJsonRequest.put("merchant_order_no", "");

                String enable_pay_channels = getBankConfig().getValueAsString("APPPayChannels");
                if (!StringHelper.isNullOrEmpty(enable_pay_channels)) {
                    alipayJsonRequest.put("enable_pay_channels", enable_pay_channels);
                }
                alipayJsonRequest.put("store_id", "");
                alipayJsonRequest.put("specified_channel", "pcredit");
                alipayJsonRequest.put("disable_pay_channels", "");

                JSONObject goods_detail = new JSONObject();
                goods_detail.put("goods_id", actItem.appId);//商品的编号
                goods_detail.put("alipay_goods_id", actItem.appId);//商品的编号
                goods_detail.put("goods_name", p_req.memo);//商品名称
                goods_detail.put("quantity", "1");//商品数量
                goods_detail.put("price", p_req.amount);//商品单价，单位为元
                goods_detail.put("goods_category", "");//商品类目
                goods_detail.put("categories_tree", "");//商品类目树
                goods_detail.put("body", "");//商品描述信息
                goods_detail.put("show_url", "");//商品的展示地址
                alipayJsonRequest.put("goods_detail", goods_detail);

                // 实名信息
                JSONObject ext_user_info = new JSONObject();
                ext_user_info.put("name", p_req.oppActName);
                ext_user_info.put("mobile", p_req.cellPhone);
                ext_user_info.put("cert_type", convertCertTypeToBank(p_req.certType));
                ext_user_info.put("cert_no", p_req.certNumber);
                ext_user_info.put("min_age", "");
                ext_user_info.put("fix_buyer", "F");

                String authFlag = "F";
                if ("1".equals(p_req.realNameFlag)) {
                    authFlag = "T";
                } else if ("0".equals(p_req.realNameFlag)) {
                    authFlag = "F";
                } else {
                    if (StringHelper.hasAnyChar(p_req.oppActName) || StringHelper.hasAnyChar(p_req.certNumber) || StringHelper.hasAnyChar(p_req.cellPhone)) {
                        authFlag = "T";
                    }
                }

                ext_user_info.put("need_check_info", authFlag);

                if ("T".equals(authFlag)) {
                    alipayJsonRequest.put("ext_user_info", ext_user_info);
                }

                if (StringHelper.hasAnyChar(actItem.sellerId)) {
                    alipayJsonRequest.put("seller_id", actItem.sellerId);
                }

                JSONObject agreement_sign_params = new JSONObject();
                agreement_sign_params.put("personal_product_code", p_req.productId);
                agreement_sign_params.put("sign_scene", "INDUSTRY");
                agreement_sign_params.put("external_agreement_no", p_req.authCode);
                agreement_sign_params.put("external_logon_id", "");

                JSONObject access_params = new JSONObject();
                access_params.put("channel", "ALIPAYAPP");
                agreement_sign_params.put("access_params", access_params);

                JSONObject sub_merchant = new JSONObject();
                sub_merchant.put("sub_merchant_id", actItem.subMerchantId);
                sub_merchant.put("sub_merchant_name", "");
                sub_merchant.put("sub_merchant_service_name", "");
                sub_merchant.put("sub_merchant_service_description", "");
                agreement_sign_params.put("sub_merchant", sub_merchant);

                JSONObject period_rule_params = new JSONObject();
                period_rule_params.put("period_type", "DAY");
                period_rule_params.put("period", DateHelper.getDifferDays(Format.Date8Format.parse(p_req.timeStart), Format.Date8Format.parse(p_req.timeExpire)));
                period_rule_params.put("execute_time", Format.Date10Format.format(p_req.getTimeStart()));
                String singleLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "singleLimit");
                if (StringHelper.isNullOrEmpty(singleLimit)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'singleLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("single_amount", singleLimit);
                String monthAmtLimit = getBankConfig().getMapValueByKey("contractKeyMapping", "monthAmtLimit");
                if (StringHelper.isNullOrEmpty(monthAmtLimit)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'monthAmtLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("total_amount", monthAmtLimit);
                String total_payments = getBankConfig().getMapValueByKey("contractKeyMapping", "countLimit");
                if (StringHelper.isNullOrEmpty(total_payments)) {
                    retAts.respCode = "-1";
                    retAts.respInfo = "缺失配置节点'countLimit'或值为空!";
                    return retAts;
                }
                period_rule_params.put("total_payments", total_payments);
                period_rule_params.put("allow_huazhi_degrade", "true");
                period_rule_params.put("sign_notify_url", actItem.notifyURL);

                agreement_sign_params.put("period_rule_params", period_rule_params);
                alipayJsonRequest.put("agreement_sign_params", agreement_sign_params);

                String bizContent = JSON.toJSONString(alipayJsonRequest);
                bizContent = bizContent.replaceAll("\\\\\\\\", "");

                AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                TreeMap<String, String> signMapParams = new TreeMap<String, String>();

                signMapParams.put("app_id", actItem.appId);
                signMapParams.put("method", "alipay.trade.app.pay");
                signMapParams.put("format", "JSON");
                signMapParams.put("charset", getCharset());
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }
                signMapParams.put("sign_type", signType);
                String timestamp = Format.DateTimeFormat.format(new Date());
                signMapParams.put("timestamp", timestamp);
                signMapParams.put("version", "1.0");
                signMapParams.put("notify_url", actItem.notifyURL);
                signMapParams.put("biz_content", bizContent);

                String mapStr = "";
                Iterator<Map.Entry<String, String>> it = signMapParams.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, String> entry = it.next();
                    mapStr += entry.getKey() + ":" + entry.getValue() + "\r\n";
                }
                WriteBankLogLn("待签名MAP:\r\n" + mapStr);

                String signData = AlipaySignature.getSignContent(signMapParams);
                WriteBankLogLn2("待签名原始数据:" + signData);

                String signature = "";
                if ("RSA2".equalsIgnoreCase(signType)) {
                    signature = AlipaySignature.rsa256Sign(signData, actItem.ownKeyStorePath, getCharset());
                } else {
                    signature = AlipaySignature.rsaSign(signData, actItem.ownKeyStorePath, getCharset());
                }
                WriteBankLogLn2("本机生成签名:\r\n" + signature);
                signMapParams.put("sign", signature);
                request.setBizContent(convertMapToStr(signMapParams));
                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.getUrl("appPayApply"), actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                WriteBankLogStep2(request.getBizContent());
                AlipayTradeAppPayResponse response = alipayClient.pageExecute(request);
                WriteBankLogStep3(response.getBody());

                if (response != null) {
                    retAts.respCode = "0";
                    retAts.respInfo = response.getMsg();
                    if ("10000".equals(response.getCode())) {
                        retAts.transState = StringHelper.joinNotEmpty("+", response.getCode(), response.getMsg());
                    } else {
                        retAts.transState = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = response.getBody();
                }
            } else {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号:[" + p_req.ownAct + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }

    @Override
    public RetAtsQueryOrder queryAppPay(ReqQueryOrder p_req) {
        RetAtsQueryOrder retAts = new RetAtsQueryOrder();
        retAts.rdSeq = p_req.rdSeq;

        try {
            logIsExist();

            ActSetItem actItem = this.getBankConfig().getActSetItem(p_req.ownAct, "unifiedorder");
            if (actItem != null) {
                String signType = "RSA2";
                boolean useSignType = getBankConfig().getValueAsBool("useSignType");
                if (useSignType) {
                    signType = actItem.signType;
                }

                AlipayClient alipayClient = new DefaultAlipayClient(bankFront.serverURL, actItem.appId,
                        actItem.ownKeyStorePath, "json", getCharset(), actItem.oppCertFilePath, signType);

                AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                request.setBizContent("{\"out_trade_no\":\"" + p_req.rdSeq + "\"}");

                WriteBankUrlLogLn(bankFront.serverURL);
                WriteBankLogStep2(request.getBizContent());

                AlipayTradeQueryResponse response = alipayClient.execute(request);
                WriteBankLogStep3(response.getBody());

                retAts.respCode = "0";
                retAts.respInfo = response.getMsg();
                if ("10000".equals(response.getCode())) {
                    retAts.transState = StringHelper.joinNotEmpty("+", response.getCode(), response.getTradeStatus());
                    retAts.payInfoCode = response.getTradeStatus();
                    retAts.outTransID = response.getTradeNo();
                    retAts.openId = response.getOpenId();
                    retAts.oppAct = response.getBuyerLogonId();
                } else {
                    retAts.transState = StringHelper.joinNotEmpty("+", response.getCode(), response.getSubCode());
                    retAts.payInfoCode = response.getSubCode();
                }
            } else {
                retAts.respCode = "-1";
                retAts.respCode = "未找到账号:[" + p_req.ownAct + "]商户配置信息";
            }
        } catch (Exception e) {
            e.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = e.getMessage();
            WriteBankLogLn(e);
        }

        return retAts;
    }
}
